package com.mrazola;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;

public class Ball {

	public static final double DEFAULT_MOVEMENT_SPEED = 240; 	// (px/s)
	public static final double DEFAULT_ROTATION_SPEED = 180; 	// (º/s)
	public static final double DEFAULT_MOVEMENT_ANGLE = 45;

	public class MovementVector {

		public double h;
		public double v;
		public double angle;

		public MovementVector(double degrees, double length) {
			this.angle = Math.toRadians(degrees);
			h = Math.cos(angle) * length;
			v = Math.sin(angle) * length;
		}

		public int displacementH(double distance, long elapsedTime) {
			return (int) Math.round(Math.cos(angle) * distance);
		}

		public int displacementV(double distance, long elapsedTime) {
			return (int) Math.round(Math.sin(angle) * distance);
		}
		
		public void updateAngle(long elapsedTime) {
			angle = angle + Math.toRadians( rotationSpeed / 20 * elapsedTime / 1000);
		}

		public void revertH() {
			h = -h;
			angle = Math.atan2(v, h);
			hasCollided = true;
			collisionTimestamp = System.currentTimeMillis();
		}

		public void revertV() {
			v = -v;
			angle = Math.atan2(v, h);
			hasCollided = true;
			collisionTimestamp = System.currentTimeMillis();
		}
		
	}

	public double movementSpeed;
	public MovementVector movementVector;
	public double rotationSpeed;
	public float orientation;

	public int x;
	public int y;
	public int width;
	public int left;
	public int top;
	public int right;
	public int bottom;

	public Rect currentPosition;
	public Rect previousPosition;
	public Rect shadowPosition;

	private Space space;
	private Drawable ball;
	private Drawable ballCollision;
	private boolean hasCollided;
	private long collisionTimestamp;

	public Ball(Space space, Context context) {

		this.ball = context.getResources().getDrawable(R.drawable.ball_v1);
		this.ballCollision = context.getResources().getDrawable(R.drawable.ball_v2);
		this.space = space;
		restartBall();

	}

	private void restartBall() {

		this.movementSpeed = DEFAULT_MOVEMENT_SPEED;
		this.rotationSpeed = DEFAULT_ROTATION_SPEED;

		this.x = space.centerX;
		this.y = space.centerY;
		//this.width = (int) Math.round(space.width * 0.1);
		this.width = 32;
		this.left = x - width / 2;
		this.right = x + width / 2;
		this.top = y - width / 2;
		this.bottom = y + width / 2;

		Rect initialPosition = new Rect(left, top, right, bottom);
		currentPosition = initialPosition;
		previousPosition = initialPosition;
		shadowPosition = initialPosition;

		//Unit vector
		movementVector = new MovementVector(DEFAULT_MOVEMENT_ANGLE, 1);
	}

	//TODO Return state
	public void updateState(Canvas sky, long elapsedTime) {
		
		//Draw trail shifting positions
		//sky.drawRect(previousPosition, new Paint());
		
		shadowPosition = previousPosition;
		previousPosition = currentPosition;
		/*
		ball.setAlpha(50);
		ball.setBounds(shadowPosition);
		ball.draw(sky);
		
		ball.setAlpha(150);
		ball.setBounds(previousPosition);
		ball.draw(sky);
		*/
		//New position and orientation
		orientation += rotationSpeed * elapsedTime / 1000;
		orientation %= 360;

		calculateNewPosition(elapsedTime);
		
		currentPosition = new Rect(left, top, right, bottom);
		sky.save();
		sky.rotate(orientation, x, y);
		ball.setAlpha(255);
		if (!hasCollided) {
			ball.setBounds(currentPosition);
			ball.draw(sky);
		} else {
			//TODO Look at TransitionDrawable
			ballCollision.setBounds(currentPosition);
			ballCollision.draw(sky);
			if (System.currentTimeMillis() - collisionTimestamp > 300) {
				hasCollided = false;
			}
		}
		sky.restore();

	}

	private void calculateNewPosition(long elapsedTime) {

		double distance = movementSpeed * elapsedTime / 1000;
		movementVector.updateAngle(elapsedTime);
		int hDistance = movementVector.displacementH(distance, elapsedTime);
		int vDistance = movementVector.displacementV(distance, elapsedTime);

		left = left + hDistance;
		top = top + vDistance;
		bottom = top + width;
		right = left + width;
		//Check bounds and revert direction if necessary
		if (left <= 0) {
			left = Math.abs(left);
			movementVector.revertH();
		}
		if (top <= 0) {
			top = Math.abs(top);
			movementVector.revertV();
		}
		if (bottom >= space.height) {
			top = top - (bottom - space.height);
			movementVector.revertV();
		}
		if (right >= space.width) {
			left = left - (right - space.width) ;
			movementVector.revertH();
		}
		bottom = top + width;
		right = left + width;
		
		x = left + width / 2;
		y = top + width / 2;
	}

}
